package org.admin.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.query.MPJQueryWrapper;
import com.github.yulichang.toolkit.JoinWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import core.data.DataHandle;
import org.admin.entity.domain.Role;
import org.admin.entity.domain.RolePermsGroup;
import org.admin.entity.domain.UserRole;
import org.admin.entity.dto.RoleDto;
import org.admin.entity.vo.RoleFetchVo;
import org.admin.entity.vo.RoleQueryVo;
import org.admin.mapper.RoleMapper;
import org.admin.mapper.RolePermsGroupMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;

@Service
public class RoleService {
    @Autowired
    RoleMapper mapper;
    @Autowired
    RolePermsGroupMapper rolePermsGroupMapper;
    @Transactional
    public void create(DataHandle<RoleDto, ?> handle) {
        RoleDto params = handle.getParams();
        Role entity = new Role();
        Date now = new Date();
        boolean doUpdate = true;
        if(params.getId() != null && params.getId() != 0){
            // 更新
            // 校验角色
            long roleCount = mapper.selectCount(new LambdaQueryWrapper<Role>().eq(Role::getId, params.getId()));
            if(roleCount == 0) {
                handle.failure("id", "指定角色不存在");
                return;
            }
            entity.setId(params.getId());
        }else{
            // 插入
            doUpdate = false;
            entity.setCreatedAt(now);
        }
        entity.setUpdateAt(now);
        entity.setName(params.getName());
        entity.setUploadWith(params.getUpload()? Role.UPLOAD.TRUE: Role.UPLOAD.FALSE);

        if(doUpdate){
            mapper.updateById(entity);
        }else{
            mapper.insert(entity);
        }
        handle.success();
    }


    public void fetch(DataHandle<RoleDto, RoleFetchVo> handle) {
        RoleDto params = handle.getParams();
        Role role = mapper.selectById(params.getId());
        if(role == null){
            handle.failure("id", "指定角色不存在");
            return;
        }
        handle.success(new RoleFetchVo() {{
            setId(role.getId());
            setName(role.getName());
            setUpload(role.getUpload());
        }});
    }
    @Transactional
    public void remove(DataHandle<RoleDto, ?> handle) {
        RoleDto params = handle.getParams();
        long count = mapper.selectCount(new LambdaQueryWrapper<Role>().in(Role::getId, params.getIds()));
        if(count != params.getIds().size()){
            handle.failure("ids", "选择了不存在的角色");
            return;
        }

        // 校验用户扩展表
        if(new MPJLambdaWrapper<>(UserRole.class)
                .in(UserRole::getRoleId, params.getIds())
                .count() > 0){
            handle.failure("ids", "请先解除与用户绑定后再试");
            return;
        }

        // 自动删除校验分表
        mapper.delete(JoinWrappers.delete(Role.class)
                .in(Role::getId, params.getIds()));
        rolePermsGroupMapper.delete(JoinWrappers.delete(RolePermsGroup.class)
                .in(RolePermsGroup::getRoleId, params.getIds()));

        handle.success();
    }


    public void query(DataHandle<RoleDto, IPage<RoleQueryVo>> handle) {
        RoleDto params = handle.getParams();

        MPJLambdaWrapper<Role> query = new MPJLambdaWrapper<>();
        query.selectAll(Role.class)
                .selectFunc(() -> "COUNT(%s)", UserRole::getId, RoleQueryVo::getUserCount)
                .leftJoin(UserRole.class, UserRole::getRoleId, Role::getId)
                .orderByDesc(Role::getCreatedAt)
                .groupBy(Role::getId);

        if(params.getName() != null && !params.getName().isEmpty()){
            query.like(Role::getName, "%" + params.getName()+ "%");
        }
        if(params.getUpload() != null){
            query.eq(Role::getUpload, params.getUpload() ? Role.UPLOAD.TRUE.getValue(): Role.UPLOAD.FALSE.getValue());
        }
        IPage<RoleQueryVo> list = mapper.selectJoinPage(new Page<>(params.getCurrent(), params.getSize()), RoleQueryVo.class, query);
        handle.success(list);
    }
}
